/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "softbus_adapter_crypto.h"

#include <securec.h>

#include "mbedtls/base64.h"
#include "mbedtls/cipher.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/entropy.h"
#include "mbedtls/gcm.h"
#include "mbedtls/md.h"
#include "mbedtls/platform.h"
#include "softbus_adapter_file.h"
#include "softbus_adapter_log.h"
#include "softbus_errcode.h"

#if defined(DEVICE_HI3519DV500) || defined(DEVICE_HISS928V100) || defined(DEVICE_HI3516CV610)
#ifdef HARDWARE_CIPHER
#include "ss_mpi_cipher.h"
#include "ss_mpi_otp.h"
#if defined(ENABLE_H9)
#include "ss_mpi_km.h"
#include "ss_mpi_sys_mem.h"
#endif
#if defined(ENABLE_H8)
#include "ss_mpi_klad.h"
#endif
#endif
#endif

#ifndef MBEDTLS_CTR_DRBG_C
#define MBEDTLS_CTR_DRBG_C
#endif

#ifndef MBEDTLS_MD_C
#define MBEDTLS_MD_C
#endif

#ifndef MBEDTLS_SHA256_C
#define MBEDTLS_SHA256_C
#endif

#ifndef MBEDTLS_ENTROPY_C
#define MBEDTLS_ENTROPY_C
#endif

#ifndef MBEDTLS_CIPHER_MODE_CTR
#define MBEDTLS_CIPHER_MODE_CTR
#endif

#ifndef MBEDTLS_AES_C
#define MBEDTLS_AES_C
#endif

#ifndef MBEDTLS_CIPHER_C
#define MBEDTLS_CIPHER_C
#endif

#define EVP_AES_128_KEYLEN 16
#define EVP_AES_256_KEYLEN 32

static SoftBusMutex g_randomLock;

#if !defined(DEVICE_HI3519DV500) && !defined(DEVICE_HISS928V100) && !defined(DEVICE_HI3516CV610)
static mbedtls_cipher_type_t GetCtrAlgorithmByKeyLen(uint32_t keyLen)
{
    switch (keyLen) {
        case EVP_AES_128_KEYLEN:
            return MBEDTLS_CIPHER_ARIA_128_CTR;
        case EVP_AES_256_KEYLEN:
            return MBEDTLS_CIPHER_ARIA_256_CTR;
        default:
            return MBEDTLS_CIPHER_NONE;
    }
    return MBEDTLS_CIPHER_NONE;
}
#endif

#if defined(DEVICE_HI3519DV500) || defined(DEVICE_HISS928V100) || defined(DEVICE_HI3516CV610)
#ifndef HARDWARE_CIPHER
static int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherkey, const unsigned char *plainText,
    uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
{
    if ((cipherkey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
        (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    int32_t ret;
    unsigned char tagBuf[TAG_LEN] = {0};
    mbedtls_gcm_context aesContext;
    mbedtls_gcm_init(&aesContext);

    ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherkey->key, cipherkey->keyLen * KEY_BITS_UNIT);
    if (ret != 0) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    ret = mbedtls_gcm_crypt_and_tag(&aesContext, MBEDTLS_GCM_ENCRYPT, plainTextSize, cipherkey->iv,
        GCM_IV_LEN, NULL, 0, plainText, cipherText + GCM_IV_LEN, TAG_LEN, tagBuf);
    if (ret != 0) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    if (memcpy_s(cipherText, cipherTextLen, cipherkey->iv, GCM_IV_LEN) != EOK) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    if (memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize,
        tagBuf, TAG_LEN) != 0) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    mbedtls_gcm_free(&aesContext);
    return (plainTextSize + OVERHEAD_LEN);
}

static int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherkey, const unsigned char *cipherText,
    uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
{
    if ((cipherkey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
        (plainLen < cipherTextSize - OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    mbedtls_gcm_context aesContext;
    mbedtls_gcm_init(&aesContext);
    int32_t ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherkey->key,
        cipherkey->keyLen * KEY_BITS_UNIT);
    if (ret != 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt mbedtls_gcm_setkey fail\n");
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_DECRYPT_ERR;
    }

    int32_t actualPlainLen = (int32_t)(cipherTextSize - OVERHEAD_LEN);
    ret = mbedtls_gcm_auth_decrypt(&aesContext, cipherTextSize - OVERHEAD_LEN, cipherkey->iv,
        GCM_IV_LEN, NULL, 0, cipherText + actualPlainLen + GCM_IV_LEN, TAG_LEN, cipherText + GCM_IV_LEN, plain);
    if (ret != 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] Decrypt mbedtls_gcm_auth_decrypt fail.[%d]\n", ret);
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_DECRYPT_ERR;
    }

    mbedtls_gcm_free(&aesContext);
    return actualPlainLen;
}
#else
#define AES128_KEY_LEN      16
#define AES192_KEY_LEN      24
#define AES256_KEY_LEN      32

#ifndef sample_chk_expr_goto
#define sample_chk_expr_goto(expr, expected_ret, label) do { \
    int _ret = expr;  \
    if (_ret != expected_ret) { \
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] %s return 0x%x\n", #expr, _ret);    \
        goto label;    \
    }   \
} while (0)
#endif

#ifndef sample_chk_expr_return
#define sample_chk_expr_return(expr, expected_ret) do { \
    int _ret = expr;  \
    if (_ret != expected_ret) { \
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] %s return 0x%x\n", #expr, _ret);    \
        return _ret;    \
    }   \
} while (0)
#endif

#ifndef sample_chk_expr_with_return
#define sample_chk_expr_with_return(expr, expected_ret, err_ret) do {  \
    int _ret = expr;    \
    if (_ret != expected_ret) { \
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] %s return 0x%x\n", #expr, _ret);    \
        return err_ret;    \
    }   \
} while (0)
#endif

#ifndef sample_chk_expr_goto_with_ret
#define sample_chk_expr_goto_with_ret(expr, expected_ret, ret, err_ret, label) do { \
    int _ret = expr;  \
    if (_ret != expected_ret) { \
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] %s return 0x%x\n", #expr, _ret);    \
        ret = err_ret;  \
        goto label;    \
    }   \
} while (0)
#endif

#if !defined(CONFIG_CHIP_SS928V100)
void cipher_free(const crypto_buf_attr *buf_attr, const void *virt_addr)
{
    if (buf_attr->phys_addr != TD_NULL && virt_addr != TD_NULL) {
        ss_mpi_sys_mmz_free(buf_attr->phys_addr, virt_addr);
    }
}

td_s32 cipher_alloc(crypto_buf_attr *buf_attr, void **virt_addr, unsigned int size)
{
    td_s32 ret;
    td_phys_addr_t phys_addr;
    ret = ss_mpi_sys_mmz_alloc(&phys_addr, virt_addr, NULL, NULL, size);
    if (ret != TD_SUCCESS) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] call ss_mpi_sys_mmz_alloc failed\n");
        return TD_FAILURE;
    }
    buf_attr->phys_addr = (unsigned long) phys_addr;
    return TD_SUCCESS;
}

static td_s32 cipher_set_clear_key(crypto_handle keyslot_handle, td_u8 *key, td_u32 keylen)
{
    td_s32 ret = TD_SUCCESS;
    crypto_handle klad_handle = 0;
    td_u32 offset = 0x12;
    td_u8 tee_enable = 0;
    km_klad_attr klad_attr = {
        .key_cfg = {
            .engine = KM_CRYPTO_ALG_AES,
            .decrypt_support = TD_TRUE,
            .encrypt_support = TD_TRUE
        }
    };
    km_klad_clear_key clear_key = {
        .key = key,
        .key_size = keylen
    };
    (void)ss_mpi_otp_init();
    (void)ss_mpi_otp_read_byte(offset, &tee_enable);
    (void)ss_mpi_otp_deinit();
    if (tee_enable == 0x42) {
        klad_attr.key_sec_cfg.key_sec = KM_KLAD_SEC_ENABLE;
        klad_attr.key_sec_cfg.master_only_enable = TD_TRUE;
        klad_attr.key_sec_cfg.dest_buf_sec_support = TD_TRUE;
        klad_attr.key_sec_cfg.src_buf_sec_support = TD_TRUE;
        klad_attr.key_sec_cfg.src_buf_non_sec_support = TD_FALSE;
        klad_attr.key_sec_cfg.dest_buf_non_sec_support = TD_FALSE;
    } else {
        klad_attr.key_sec_cfg.key_sec = KM_KLAD_SEC_DISABLE;
        klad_attr.key_sec_cfg.master_only_enable = TD_FALSE;
        klad_attr.key_sec_cfg.dest_buf_sec_support = TD_FALSE;
        klad_attr.key_sec_cfg.dest_buf_non_sec_support = TD_TRUE;
        klad_attr.key_sec_cfg.src_buf_sec_support = TD_FALSE;
        klad_attr.key_sec_cfg.src_buf_non_sec_support = TD_TRUE;
    }

    /* 1. klad create handle */
    sample_chk_expr_return(ss_mpi_klad_create(&klad_handle), TD_SUCCESS);

    /* 2. klad set attr for clear key */
    sample_chk_expr_goto(ss_mpi_klad_set_attr(klad_handle, &klad_attr), TD_SUCCESS, __KLAD_DESTORY__);

    /* 3. attach klad handle & kslot handle */
    sample_chk_expr_goto(ss_mpi_klad_attach(klad_handle, KM_KLAD_DEST_TYPE_MCIPHER, keyslot_handle),
        TD_SUCCESS, __KLAD_DESTORY__);

    /* 4. set clear key */
    sample_chk_expr_goto(ss_mpi_klad_set_clear_key(klad_handle, &clear_key), TD_SUCCESS, __KLAD_DETACH__);

__KLAD_DETACH__:
    ss_mpi_klad_detach(klad_handle, KM_KLAD_DEST_TYPE_MCIPHER, keyslot_handle);
__KLAD_DESTORY__:
    ss_mpi_klad_destroy(klad_handle);
    return ret;
}

/* sample aes ccm/gcm */
static int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherkey, const unsigned char *plainText,
    uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
{
    if ((cipherkey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
        (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    td_s32 ret = TD_SUCCESS;
    td_handle symc_handle = 0;
    crypto_handle keyslot_handle = 0;
    crypto_buf_attr src_buf = {0};
    crypto_buf_attr dst_buf = {0};
    td_u32 length = plainTextSize;
    crypto_symc_config_aes_ccm_gcm ccm_gcm_config = {
        .aad_len = 0,
        .data_len = length,
        .tag_len = TAG_LEN
    };

    void *src_virt_addr = TD_NULL;
    void *dst_virt_addr = TD_NULL;
    td_u8 enc_tag[TAG_LEN] = {0};
    crypto_symc_attr symc_attr = {
                .symc_type = CRYPTO_SYMC_TYPE_NORMAL,
                .is_long_term = TD_FALSE,
    };
    crypto_symc_ctrl_t symc_ctrl = {
                .symc_alg = CRYPTO_SYMC_ALG_AES,
                .work_mode = CRYPTO_SYMC_WORK_MODE_GCM,
                .symc_key_length = CRYPTO_SYMC_KEY_256BIT,
                .symc_bit_width = CRYPTO_SYMC_BIT_WIDTH_128BIT,
                .iv_change_flag = CRYPTO_SYMC_GCM_IV_CHANGE_START,
                .iv_length = GCM_IV_LEN,
    };

    symc_ctrl.param = (void *)&ccm_gcm_config;
    sample_chk_expr_goto(cipher_alloc(&src_buf, (void **)&src_virt_addr, length), TD_SUCCESS, CIPHER_FREE);
    sample_chk_expr_goto(cipher_alloc(&dst_buf, (void **)&dst_virt_addr, length), TD_SUCCESS, CIPHER_FREE);

    /* 1. cipher init */
    sample_chk_expr_goto(ss_mpi_cipher_symc_init(), TD_SUCCESS, CIPHER_FREE);

    /* 2. km init */
    sample_chk_expr_goto(ss_mpi_km_init(), TD_SUCCESS, CIPHER_DEINIT);

    /* 3. cipher create handle */
    sample_chk_expr_goto(ss_mpi_cipher_symc_create(&symc_handle, &symc_attr), TD_SUCCESS, KM_DEINIT);

    /* 4. create keyslot handle */
    sample_chk_expr_goto(ss_mpi_keyslot_create(&keyslot_handle, KM_KEYSLOT_TYPE_MCIPHER), TD_SUCCESS,
        CIPHER_DESTROY);

    /* 5. attach cipher handle & kslot handle */
    sample_chk_expr_goto(ss_mpi_cipher_symc_attach(symc_handle, (td_handle)keyslot_handle), TD_SUCCESS,
        KEYSLOT_DESTROY);

    sample_chk_expr_goto_with_ret(memcpy_s(symc_ctrl.iv, GCM_IV_LEN, cipherkey->iv, GCM_IV_LEN),
        EOK, ret, TD_FAILURE, KEYSLOT_DESTROY);
    /* 6. set clear key */
    sample_chk_expr_goto(cipher_set_clear_key(keyslot_handle, (unsigned char *)cipherkey->key, cipherkey->keyLen), TD_SUCCESS, KEYSLOT_DESTROY);
    /* 7.2. encrypt */

    /* 7. encrypt */
    /* 7.1 set config for encrypt */
    sample_chk_expr_goto(ss_mpi_cipher_symc_set_config(symc_handle, &symc_ctrl), TD_SUCCESS,
        KEYSLOT_DESTROY);
    /* 7.2. encrypt */
    sample_chk_expr_goto_with_ret(memcpy_s(src_virt_addr, length, plainText, length),
        EOK, ret, TD_FAILURE, KEYSLOT_DESTROY);
    (void)memset_s(dst_virt_addr, length, 0, length);
    sample_chk_expr_goto(ss_mpi_cipher_symc_encrypt(symc_handle, &src_buf, &dst_buf, length), TD_SUCCESS,
        KEYSLOT_DESTROY);
    /* 7.3 get encrypt tag */
    sample_chk_expr_goto(ss_mpi_cipher_symc_get_tag(symc_handle, enc_tag, TAG_LEN), TD_SUCCESS,
        KEYSLOT_DESTROY);

    sample_chk_expr_goto((memcpy_s(cipherText, cipherTextLen, cipherkey->iv, GCM_IV_LEN) != 0),
        TD_SUCCESS, KEYSLOT_DESTROY);

    sample_chk_expr_goto((memcpy_s(cipherText + GCM_IV_LEN, cipherTextLen - GCM_IV_LEN , dst_virt_addr, plainTextSize) != 0),
        TD_SUCCESS, KEYSLOT_DESTROY);

    sample_chk_expr_goto((memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize,
        enc_tag, TAG_LEN) != 0),
        TD_SUCCESS, KEYSLOT_DESTROY);
    ret = plainTextSize + GCM_IV_LEN + TAG_LEN;
KEYSLOT_DESTROY:
    ss_mpi_keyslot_destroy(keyslot_handle);
CIPHER_DESTROY:
    ss_mpi_cipher_symc_destroy(symc_handle);
KM_DEINIT:
    ss_mpi_km_deinit();
CIPHER_DEINIT:
    ss_mpi_cipher_symc_deinit();
CIPHER_FREE:
    cipher_free(&src_buf, src_virt_addr);
    cipher_free(&dst_buf, dst_virt_addr);

    return ret;
}

static int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherkey, const unsigned char *cipherText,
    uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
{
    if ((cipherkey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
        (plainLen < cipherTextSize - OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }
    td_s32 ret = TD_SUCCESS;
    td_handle symc_handle = 0;
    crypto_handle keyslot_handle = 0;
    crypto_buf_attr src_buf = {0};
    crypto_buf_attr dst_buf = {0};
    td_u32 length = cipherTextSize - GCM_IV_LEN - TAG_LEN;
    crypto_symc_config_aes_ccm_gcm ccm_gcm_config = {
        .aad_len = 0,
        .data_len = length,
        .tag_len = AES128_KEY_LEN
    };

    void *src_virt_addr = TD_NULL;
    void *dst_virt_addr = TD_NULL;

    td_u8 dec_tag[TAG_LEN] = {0};
    crypto_symc_attr symc_attr= {
                .symc_type = CRYPTO_SYMC_TYPE_NORMAL,
                .is_long_term = TD_FALSE,
    };
    crypto_symc_ctrl_t symc_ctrl= {
                .symc_alg = CRYPTO_SYMC_ALG_AES,
                .work_mode = CRYPTO_SYMC_WORK_MODE_GCM,
                .symc_key_length = CRYPTO_SYMC_KEY_256BIT,
                .symc_bit_width = CRYPTO_SYMC_BIT_WIDTH_128BIT,
                .iv_change_flag = CRYPTO_SYMC_GCM_IV_CHANGE_START,
                .iv_length = GCM_IV_LEN,
    };

    symc_ctrl.param = (void *)&ccm_gcm_config;
    sample_chk_expr_goto(cipher_alloc(&src_buf, (void **)&src_virt_addr, length), TD_SUCCESS, CIPHER_FREE);
    sample_chk_expr_goto(cipher_alloc(&dst_buf, (void **)&dst_virt_addr, length), TD_SUCCESS, CIPHER_FREE);

    /* 1. cipher init */
    sample_chk_expr_goto(ss_mpi_cipher_symc_init(), TD_SUCCESS, CIPHER_FREE);

    /* 2. km init */
    sample_chk_expr_goto(ss_mpi_km_init(), TD_SUCCESS, CIPHER_DEINIT);

    /* 3. cipher create handle */
    sample_chk_expr_goto(ss_mpi_cipher_symc_create(&symc_handle, &symc_attr), TD_SUCCESS, KM_DEINIT);

    /* 4. create keyslot handle */
    sample_chk_expr_goto(ss_mpi_keyslot_create(&keyslot_handle, KM_KEYSLOT_TYPE_MCIPHER), TD_SUCCESS,
        CIPHER_DESTROY);

    /* 5. attach cipher handle & kslot handle */
    sample_chk_expr_goto(ss_mpi_cipher_symc_attach(symc_handle, (td_handle)keyslot_handle), TD_SUCCESS,
        KEYSLOT_DESTROY);
    sample_chk_expr_goto_with_ret(memcpy_s(symc_ctrl.iv, GCM_IV_LEN, cipherkey->iv, GCM_IV_LEN),
        EOK, ret, TD_FAILURE, KEYSLOT_DESTROY);
    /* 6. set clear key */
    sample_chk_expr_goto(cipher_set_clear_key(keyslot_handle, (unsigned char *)cipherkey->key, cipherkey->keyLen),
        TD_SUCCESS, KEYSLOT_DESTROY);

    /* 8. decrypt */
    /* 8.1 set config for decrypt */
    sample_chk_expr_goto(ss_mpi_cipher_symc_set_config(symc_handle, &symc_ctrl), TD_SUCCESS,
        KEYSLOT_DESTROY);
    /* 8.2. decrypt */
    sample_chk_expr_goto_with_ret(memcpy_s(src_virt_addr, length, cipherText + GCM_IV_LEN, length), EOK, ret,
        TD_FAILURE, KEYSLOT_DESTROY);
    (void)memset_s(dst_virt_addr, length, 0, length);
    sample_chk_expr_goto(ss_mpi_cipher_symc_decrypt(symc_handle, &src_buf, &dst_buf, length), TD_SUCCESS,
        KEYSLOT_DESTROY);
    /* 8.3 get decrypt tag */
    sample_chk_expr_goto(ss_mpi_cipher_symc_get_tag(symc_handle, dec_tag, TAG_LEN), TD_SUCCESS,
        KEYSLOT_DESTROY);

    sample_chk_expr_goto_with_ret(
        memcpy_s(plain, plainLen, dst_virt_addr, length),
        EOK, ret, TD_FAILURE, KEYSLOT_DESTROY);
        ret = length;
KEYSLOT_DESTROY:
    ss_mpi_keyslot_destroy(keyslot_handle);
CIPHER_DESTROY:
    ss_mpi_cipher_symc_destroy(symc_handle);
KM_DEINIT:
    ss_mpi_km_deinit();
CIPHER_DEINIT:
    ss_mpi_cipher_symc_deinit();
CIPHER_FREE:
    cipher_free(&src_buf, src_virt_addr);
    cipher_free(&dst_buf, dst_virt_addr);

    return ret;

}
#else
static td_s32 cipher_set_clear_key(td_handle keyslot_handle, td_u8 *key, td_u32 keylen)
{
    td_s32 ret = TD_SUCCESS;
    td_handle klad_handle = 0;
    ot_klad_attr klad_attr = {
        .klad_cfg = {
            .klad_type = OT_KLAD_TYPE_CLEARCW,
        },
    };

    ot_klad_clear_key clear_key = {
        .key_size = keylen
    };

    sample_chk_expr_goto(memcpy_s(clear_key.key, OT_KLAD_MAX_KEY_LEN, key, keylen), EOK, __KEY_CLEAN__);

    /* 1. klad create handle */
    sample_chk_expr_goto(ss_mpi_klad_create(&klad_handle), TD_SUCCESS, __KEY_CLEAN__);

    /* 2. klad set attr for clear key */
    sample_chk_expr_goto(ss_mpi_klad_set_attr(klad_handle, &klad_attr), TD_SUCCESS, __KLAD_DESTORY__);

    /* 3. attach klad handle & kslot handle */
    sample_chk_expr_goto(ss_mpi_klad_attach(klad_handle, keyslot_handle), TD_SUCCESS, __KLAD_DESTORY__);

    /* 4. set clear key */
    sample_chk_expr_goto(ss_mpi_klad_set_clear_key(klad_handle, &clear_key), TD_SUCCESS, __KLAD_DETACH__);

__KLAD_DETACH__:
    ss_mpi_klad_detach(klad_handle, keyslot_handle);
__KLAD_DESTORY__:
    ss_mpi_klad_destroy(klad_handle);
__KEY_CLEAN__:
    memset_s(clear_key.key, OT_KLAD_MAX_KEY_LEN, 0, OT_KLAD_MAX_KEY_LEN);
    return ret;
}

static void symc_ctrl_init(ot_cipher_ctrl *symc_ctrl, const AesGcmCipherKey *cipherkey)
{
    symc_ctrl->alg = OT_CIPHER_ALG_AES;
    symc_ctrl->work_mode = OT_CIPHER_WORK_MODE_GCM;
    symc_ctrl->aes_ccm_gcm_ctrl.iv_len = GCM_IV_LEN;
    symc_ctrl->aes_ccm_gcm_ctrl.key_len = OT_CIPHER_KEY_AES_256BIT;
    symc_ctrl->aes_ccm_gcm_ctrl.aad_len = 0;
    symc_ctrl->aes_ccm_gcm_ctrl.tag_len = TAG_LEN;

    (void)memcpy_s(symc_ctrl->aes_ccm_gcm_ctrl.iv, sizeof(symc_ctrl->aes_ccm_gcm_ctrl.iv), cipherkey->iv, GCM_IV_LEN);
}

/* sample aes ccm/gcm */
static int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherkey, const unsigned char *plainText,
    uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
{
    if ((cipherkey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
        (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    td_s32 ret = TD_FAILURE;
    td_handle symc_handle = {0};
    ot_cipher_attr symc_attr = {0};
    ot_cipher_ctrl symc_ctrl = {0};
    td_handle keyslot_handle = 0;
    ot_keyslot_attr keyslot_attr = {0};
    td_u8 enc_tag[TAG_LEN] = {0};

    keyslot_attr.type =  OT_KEYSLOT_TYPE_MCIPHER;
    keyslot_attr.secure_mode = OT_KEYSLOT_SECURE_MODE_NONE;
    symc_attr.cipher_type = OT_CIPHER_TYPE_NORMAL;

    symc_ctrl_init(&symc_ctrl, cipherkey);
    /* 1. cipher init */
    sample_chk_expr_goto(ss_mpi_cipher_init(), TD_SUCCESS, CLEAN_EXIT);

    /* 2. km init */
    sample_chk_expr_goto(ss_mpi_klad_init(), TD_SUCCESS, CIPHER_DEINIT);

    /* 3. cipher create handle */
    sample_chk_expr_goto(ss_mpi_cipher_create(&symc_handle, &symc_attr), TD_SUCCESS, KM_DEINIT);

    /* 4. create keyslot handle */
    sample_chk_expr_goto(ss_mpi_keyslot_create(&keyslot_attr, &keyslot_handle), TD_SUCCESS, CIPHER_DESTROY);

    /* 5. attach cipher handle & kslot handle */
    sample_chk_expr_goto(ss_mpi_cipher_attach(symc_handle, keyslot_handle), TD_SUCCESS, KEYSLOT_DESTROY);

    /* 6. set clear key */
    sample_chk_expr_goto(cipher_set_clear_key(keyslot_handle, (unsigned char *)cipherkey->key, cipherkey->keyLen),
        TD_SUCCESS, CIPHER_DETACH);
    /* 7.2. encrypt */

    /* 7. encrypt */
    /* 7.1 set config for encrypt */
    sample_chk_expr_goto(ss_mpi_cipher_set_cfg(symc_handle, &symc_ctrl), TD_SUCCESS, CIPHER_DETACH);
    /* 7.2. encrypt */
    sample_chk_expr_goto(ss_mpi_cipher_encrypt_virt(symc_handle, plainText, cipherText + GCM_IV_LEN, plainTextSize),
        TD_SUCCESS, CIPHER_DETACH);
    /* 7.3 get encrypt tag */
    sample_chk_expr_goto(ss_mpi_cipher_get_tag(symc_handle, enc_tag, TAG_LEN), TD_SUCCESS, CIPHER_DETACH);

    sample_chk_expr_goto((memcpy_s(cipherText, cipherTextLen, cipherkey->iv, GCM_IV_LEN) != 0),
        TD_SUCCESS, CIPHER_DETACH);

    sample_chk_expr_goto((memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize,
        enc_tag, TAG_LEN) != 0), TD_SUCCESS, CIPHER_DETACH);

    ret = plainTextSize + GCM_IV_LEN + TAG_LEN;
CIPHER_DETACH:
    ss_mpi_cipher_detach(symc_handle, keyslot_handle);
KEYSLOT_DESTROY:
    ss_mpi_keyslot_destroy(keyslot_handle);
CIPHER_DESTROY:
    ss_mpi_cipher_destroy(symc_handle);
KM_DEINIT:
    ss_mpi_klad_deinit();
CIPHER_DEINIT:
    ss_mpi_cipher_deinit();
CLEAN_EXIT:
    memset_s(symc_ctrl.aes_ccm_gcm_ctrl.iv, sizeof(symc_ctrl.aes_ccm_gcm_ctrl.iv), 0,
        sizeof(symc_ctrl.aes_ccm_gcm_ctrl.iv));

    return ret;
}

static int32_t VerifyDecryptTag(const unsigned char *cipherText, td_u32 length,
    td_u8 dec_tag[], unsigned char *plain, uint32_t plainLen)
{
    const td_u8 *tag = NULL;
    int diff = 0;

    tag = cipherText + GCM_IV_LEN + length;
    for (int i = 0; i < TAG_LEN; ++i) {
        diff = dec_tag[i] ^ tag[i];
        if (diff != 0) {
            memset_s(plain, plainLen, 0, plainLen);
            return TD_FAILURE;
        }
    }
    return TD_SUCCESS;
}

static int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherkey, const unsigned char *cipherText,
    uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
{
    if ((cipherkey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
        (plainLen < cipherTextSize - OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    td_s32 ret = TD_FAILURE;
    td_u32 length = cipherTextSize - GCM_IV_LEN - TAG_LEN;
    td_u8 dec_tag[TAG_LEN] = {0};
    td_handle symc_handle = {0};
    ot_cipher_attr symc_attr = {0};
    ot_cipher_ctrl symc_ctrl = {0};
    td_handle keyslot_handle = 0;
    ot_keyslot_attr keyslot_attr = {0};

    keyslot_attr.type =  OT_KEYSLOT_TYPE_MCIPHER;
    keyslot_attr.secure_mode = OT_KEYSLOT_SECURE_MODE_NONE;
    symc_attr.cipher_type = OT_CIPHER_TYPE_NORMAL;

    symc_ctrl_init(&symc_ctrl, cipherkey);
    /* 1. cipher init */
    sample_chk_expr_goto(ss_mpi_cipher_init(), TD_SUCCESS, CLEAN_EXIT);

    /* 2. km init */
    sample_chk_expr_goto(ss_mpi_klad_init(), TD_SUCCESS, CIPHER_DEINIT);

    /* 3. cipher create handle */
    sample_chk_expr_goto(ss_mpi_cipher_create(&symc_handle, &symc_attr), TD_SUCCESS, KM_DEINIT);

    /* 4. create keyslot handle */
    sample_chk_expr_goto(ss_mpi_keyslot_create(&keyslot_attr, &keyslot_handle), TD_SUCCESS, CIPHER_DESTROY);

    /* 5. attach cipher handle & kslot handle */
    sample_chk_expr_goto(ss_mpi_cipher_attach(symc_handle, keyslot_handle), TD_SUCCESS, KEYSLOT_DESTROY);

    /* 6. set clear key */
    sample_chk_expr_goto(cipher_set_clear_key(keyslot_handle, (unsigned char *)cipherkey->key, cipherkey->keyLen),
        TD_SUCCESS, CIPHER_DETACH);

    /* 8. decrypt */
    /* 8.1 set config for decrypt */
    sample_chk_expr_goto(ss_mpi_cipher_set_cfg(symc_handle, &symc_ctrl), TD_SUCCESS, CIPHER_DETACH);
    /* 8.2. decrypt */
    sample_chk_expr_goto(ss_mpi_cipher_decrypt_virt(symc_handle, cipherText + GCM_IV_LEN, plain, plainLen),
        TD_SUCCESS, CIPHER_DETACH);
    /* 8.3 get decrypt tag */
    sample_chk_expr_goto(ss_mpi_cipher_get_tag(symc_handle, dec_tag, TAG_LEN), TD_SUCCESS, CIPHER_DETACH);
    /* 8.4 verify decrypt tag */
    sample_chk_expr_goto(VerifyDecryptTag(cipherText, length, dec_tag, plain, plainLen), TD_SUCCESS, CIPHER_DETACH);

    ret = length;
CIPHER_DETACH:
    ss_mpi_cipher_detach(symc_handle, keyslot_handle);
KEYSLOT_DESTROY:
    ss_mpi_keyslot_destroy(keyslot_handle);
CIPHER_DESTROY:
    ss_mpi_cipher_destroy(symc_handle);
KM_DEINIT:
    ss_mpi_klad_deinit();
CIPHER_DEINIT:
    ss_mpi_cipher_deinit();
CLEAN_EXIT:
    memset_s(symc_ctrl.aes_ccm_gcm_ctrl.iv, sizeof(symc_ctrl.aes_ccm_gcm_ctrl.iv), 0,
        sizeof(symc_ctrl.aes_ccm_gcm_ctrl.iv));
    return ret;
}
#endif /* CONFIG_CHIP_SS626V100 */
#endif /* HARDWARE_CIPHER */

static mbedtls_cipher_type_t GetCtrAlgorithmByKeyLen(uint32_t keyLen)
{
    switch (keyLen) {
        case EVP_AES_128_KEYLEN:
            return MBEDTLS_CIPHER_ARIA_128_CTR;
        case EVP_AES_256_KEYLEN:
            return MBEDTLS_CIPHER_ARIA_256_CTR;
        default:
            return MBEDTLS_CIPHER_NONE;
    }
    return MBEDTLS_CIPHER_NONE;
}
#else
static int32_t MbedAesGcmEncrypt(const AesGcmCipherKey *cipherkey, const unsigned char *plainText,
    uint32_t plainTextSize, unsigned char *cipherText, uint32_t cipherTextLen)
{
    if ((cipherkey == NULL) || (plainText == NULL) || (plainTextSize == 0) || cipherText == NULL ||
        (cipherTextLen < plainTextSize + OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Encrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    int32_t ret;
    unsigned char tagBuf[TAG_LEN] = {0};
    mbedtls_gcm_context aesContext;
    mbedtls_gcm_init(&aesContext);

    ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherkey->key, cipherkey->keyLen * KEY_BITS_UNIT);
    if (ret != 0) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    ret = mbedtls_gcm_crypt_and_tag(&aesContext, MBEDTLS_GCM_ENCRYPT, plainTextSize, cipherkey->iv,
        GCM_IV_LEN, NULL, 0, plainText, cipherText + GCM_IV_LEN, TAG_LEN, tagBuf);
    if (ret != 0) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    if (memcpy_s(cipherText, cipherTextLen, cipherkey->iv, GCM_IV_LEN) != EOK) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    if (memcpy_s(cipherText + GCM_IV_LEN + plainTextSize, cipherTextLen - GCM_IV_LEN - plainTextSize,
        tagBuf, TAG_LEN) != 0) {
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_ENCRYPT_ERR;
    }

    mbedtls_gcm_free(&aesContext);
    return (plainTextSize + OVERHEAD_LEN);
}

static int32_t MbedAesGcmDecrypt(const AesGcmCipherKey *cipherkey, const unsigned char *cipherText,
    uint32_t cipherTextSize, unsigned char *plain, uint32_t plainLen)
{
    if ((cipherkey == NULL) || (cipherText == NULL) || (cipherTextSize <= OVERHEAD_LEN) || plain == NULL ||
        (plainLen < cipherTextSize - OVERHEAD_LEN)) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt invalid para\n");
        return SOFTBUS_INVALID_PARAM;
    }

    mbedtls_gcm_context aesContext;
    mbedtls_gcm_init(&aesContext);
    int32_t ret = mbedtls_gcm_setkey(&aesContext, MBEDTLS_CIPHER_ID_AES, cipherkey->key,
        cipherkey->keyLen * KEY_BITS_UNIT);
    if (ret != 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "Decrypt mbedtls_gcm_setkey fail\n");
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_DECRYPT_ERR;
    }

    int32_t actualPlainLen = (int32_t)(cipherTextSize - OVERHEAD_LEN);
    ret = mbedtls_gcm_auth_decrypt(&aesContext, cipherTextSize - OVERHEAD_LEN, cipherkey->iv,
        GCM_IV_LEN, NULL, 0, cipherText + actualPlainLen + GCM_IV_LEN, TAG_LEN, cipherText + GCM_IV_LEN, plain);
    if (ret != 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "[TRANS] Decrypt mbedtls_gcm_auth_decrypt fail.[%d]\n", ret);
        mbedtls_gcm_free(&aesContext);
        return SOFTBUS_DECRYPT_ERR;
    }

    mbedtls_gcm_free(&aesContext);
    return actualPlainLen;
}
#endif

static int32_t HandleError(mbedtls_cipher_context_t *ctx, const char *buf)
{
    if (buf != NULL) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "%{public}s", buf);
    }
    if (ctx != NULL) {
        mbedtls_cipher_free(ctx);
    }
    return SOFTBUS_DECRYPT_ERR;
}

int32_t SoftBusBase64Encode(unsigned char *dst, size_t dlen,
    size_t *olen, const unsigned char *src, size_t slen)
{
    if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
        return SOFTBUS_INVALID_PARAM;
    }
    return mbedtls_base64_encode(dst, dlen, olen, src, slen);
}

int32_t SoftBusBase64Decode(unsigned char *dst, size_t dlen,
    size_t *olen, const unsigned char *src, size_t slen)
{
    if (dst == NULL || dlen == 0 || olen == NULL || src == NULL || slen == 0) {
        return SOFTBUS_INVALID_PARAM;
    }
    return mbedtls_base64_decode(dst, dlen, olen, src, slen);
}

int32_t SoftBusGenerateStrHash(const unsigned char *str, uint32_t len, unsigned char *hash)
{
    if (str == NULL || hash == NULL || len == 0) {
        return SOFTBUS_INVALID_PARAM;
    }

    mbedtls_md_context_t ctx;
    const mbedtls_md_info_t *info = NULL;
    mbedtls_md_init(&ctx);

    info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
    if (mbedtls_md_setup(&ctx, info, 0) != 0) {
        mbedtls_md_free(&ctx);
        return SOFTBUS_ENCRYPT_ERR;
    }
    if (mbedtls_md_starts(&ctx) != 0) {
        mbedtls_md_free(&ctx);
        return SOFTBUS_ENCRYPT_ERR;
    }
    if (mbedtls_md_update(&ctx, str, len) != 0) {
        mbedtls_md_free(&ctx);
        return SOFTBUS_ENCRYPT_ERR;
    }
    if (mbedtls_md_finish(&ctx, hash) != 0) {
        mbedtls_md_free(&ctx);
        return SOFTBUS_ENCRYPT_ERR;
    }

    mbedtls_md_free(&ctx);
    return SOFTBUS_OK;
}

int32_t SoftBusGenerateRandomArray(unsigned char *randStr, uint32_t len)
{
    if (randStr == NULL || len == 0) {
        return SOFTBUS_INVALID_PARAM;
    }

    static mbedtls_entropy_context entropy;
    static mbedtls_ctr_drbg_context ctrDrbg;
    static bool initFlag = false;
    int32_t ret;

    if (initFlag == false) {
        if (SoftBusMutexInit(&g_randomLock, NULL) != SOFTBUS_OK) {
            HILOG_ERROR(SOFTBUS_HILOG_ID, "SoftBusGenerateRandomArray init lock fail");
            return SOFTBUS_LOCK_ERR;
        }
#ifdef __LITEOS_M__
    if (SoftBusMutexLock(&g_randomLock) != SOFTBUS_OK) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "SoftBusGenerateRandomArray lock fail");
        return SOFTBUS_LOCK_ERR;
    }
#endif
        mbedtls_ctr_drbg_init(&ctrDrbg);
        mbedtls_entropy_init(&entropy);
        ret = mbedtls_ctr_drbg_seed(&ctrDrbg, mbedtls_entropy_func, &entropy, NULL, 0);
        if (ret != 0) {
            SoftBusMutexUnlock(&g_randomLock);
            HILOG_ERROR(SOFTBUS_HILOG_ID, "gen random seed error, ret[%d]", ret);
            return SOFTBUS_ERR;
        }
        initFlag = true;
    }
#ifndef __LITEOS_M__

    if (SoftBusMutexLock(&g_randomLock) != SOFTBUS_OK) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "SoftBusGenerateRandomArray lock fail");
        return SOFTBUS_LOCK_ERR;
    }
#endif

    ret = mbedtls_ctr_drbg_random(&ctrDrbg, randStr, len);
    SoftBusMutexUnlock(&g_randomLock);
    if (ret != 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "gen random error, ret[%d]", ret);
        return SOFTBUS_ERR;
    }
    return SOFTBUS_OK;
}

int32_t SoftBusGenerateSessionKey(char *key, uint32_t len)
{
    if (SoftBusGenerateRandomArray((unsigned char *)key, len) != SOFTBUS_OK) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "generate sessionKey error.");
        return SOFTBUS_ENCRYPT_ERR;
    }
    return SOFTBUS_OK;
}

int32_t SoftBusEncryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
    unsigned char *encryptData, uint32_t *encryptLen)
{
    HILOG_INFO(SOFTBUS_HILOG_ID, "Encrypt Data begin");
    if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
        return SOFTBUS_INVALID_PARAM;
    }

    if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "generate random iv error.");
        return SOFTBUS_ENCRYPT_ERR;
    }
    uint32_t outLen = inLen + OVERHEAD_LEN;
    int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
    if (result <= 0) {
        return SOFTBUS_ENCRYPT_ERR;
    }
    *encryptLen = result;
    HILOG_INFO(SOFTBUS_HILOG_ID, "Encrypt Data end");
    return SOFTBUS_OK;
}

int32_t SoftBusEncryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
    unsigned char *encryptData, uint32_t *encryptLen, int32_t seqNum)
{
    if (cipherKey == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
        return SOFTBUS_INVALID_PARAM;
    }
    if (SoftBusGenerateRandomArray(cipherKey->iv, sizeof(cipherKey->iv)) != SOFTBUS_OK) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "generate random iv error.");
        return SOFTBUS_ENCRYPT_ERR;
    }
    if (memcpy_s(cipherKey->iv, sizeof(int32_t), &seqNum, sizeof(int32_t)) != EOK) {
        return SOFTBUS_ENCRYPT_ERR;
    }
    uint32_t outLen = inLen + OVERHEAD_LEN;
    int32_t result = MbedAesGcmEncrypt(cipherKey, input, inLen, encryptData, outLen);
    if (result <= 0) {
        return SOFTBUS_ENCRYPT_ERR;
    }
    *encryptLen = result;
    return SOFTBUS_OK;
}

int32_t SoftBusDecryptData(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
    unsigned char *decryptData, uint32_t *decryptLen)
{
    HILOG_INFO(SOFTBUS_HILOG_ID, "Decrypt Data begin");
    if (cipherKey == NULL || input == NULL || inLen < GCM_IV_LEN || decryptData == NULL || decryptLen == NULL) {
        return SOFTBUS_INVALID_PARAM;
    }

    if (memcpy_s(cipherKey->iv, sizeof(cipherKey->iv), input, GCM_IV_LEN) != EOK) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "copy iv failed.");
        return SOFTBUS_ENCRYPT_ERR;
    }
    uint32_t outLen = inLen - OVERHEAD_LEN;
    int32_t result = MbedAesGcmDecrypt(cipherKey, input, inLen, decryptData, outLen);
    if (result <= 0) {
        return SOFTBUS_ENCRYPT_ERR;
    }
    *decryptLen = (uint32_t)result;
    HILOG_INFO(SOFTBUS_HILOG_ID, "Decrypt Data end");
    return SOFTBUS_OK;
}

int32_t SoftBusDecryptDataWithSeq(AesGcmCipherKey *cipherKey, const unsigned char *input, uint32_t inLen,
    unsigned char *decryptData, uint32_t *decryptLen, int32_t seqNum)
{
    (void)seqNum;
    return SoftBusDecryptData(cipherKey, input, inLen, decryptData, decryptLen);
}

uint32_t SoftBusCryptoRand(void)
{
    int32_t fd = SoftBusOpenFile("/dev/urandom", SOFTBUS_O_RDONLY);
    if (fd < 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "CryptoRand open file fail");
        return 0;
    }
    uint32_t value = 0;
    int32_t len = SoftBusReadFile(fd, &value, sizeof(uint32_t));
    if (len < 0) {
        HILOG_ERROR(SOFTBUS_HILOG_ID, "CryptoRand read file fail");
        SoftBusCloseFile(fd);
        return 0;
    }
    SoftBusCloseFile(fd);
    return value;
}

int32_t SoftBusEncryptDataByCtr(AesCtrCipherKey *key, const unsigned char *input, uint32_t inLen,
    unsigned char *encryptData, uint32_t *encryptLen)
{
    if (key == NULL || input == NULL || inLen == 0 || encryptData == NULL || encryptLen == NULL) {
        return SOFTBUS_INVALID_PARAM;
    }
    mbedtls_cipher_type_t type = GetCtrAlgorithmByKeyLen(key->keyLen);
    if (type == MBEDTLS_CIPHER_NONE) {
        return HandleError(NULL, "get cipher failed");
    }
    size_t len = 0;
    *encryptLen = 0;
    mbedtls_cipher_context_t ctx;
    const mbedtls_cipher_info_t *info = NULL;
    mbedtls_cipher_init(&ctx);
    if (!(info = mbedtls_cipher_info_from_type(type))) {
        return HandleError(&ctx, "mbedtls_cipher_info_from_type ctr failed");
    }
    if (mbedtls_cipher_setup(&ctx, info) != 0) {
        return HandleError(&ctx, "mbedtls_cipher_setup ctr failed");
    }
    if (mbedtls_cipher_setkey(&ctx, key->key, key->keyLen * 8, MBEDTLS_ENCRYPT) != 0) {
        return HandleError(&ctx, "mbedtls_cipher_setkey ctr failed");
    }
    if (mbedtls_cipher_set_iv(&ctx, key->iv, BLE_BROADCAST_IV_LEN) != 0) {
        return HandleError(&ctx, "mbedtls_cipher_set_iv ctr failed");
    }
    if (mbedtls_cipher_update(&ctx, input, inLen, encryptData, &len) != 0) {
        return HandleError(&ctx, "mbedtls_cipher_update ctr failed");
    }
    *encryptLen += len;
    if (mbedtls_cipher_finish(&ctx, encryptData, &len) != 0) {
        return HandleError(&ctx, "mbedtls_cipher_finish ctr failed");
    }
    *encryptLen += len;
    mbedtls_cipher_free(&ctx);
    return SOFTBUS_OK;
}

int32_t SoftBusDecryptDataByCtr(AesCtrCipherKey *key, const unsigned char *input, uint32_t inLen,
    unsigned char *decryptData, uint32_t *decryptLen)
{
    return SoftBusEncryptDataByCtr(key, input, inLen, decryptData, decryptLen);
}
